﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Reflection;

namespace Avatar.ClientDevice
{
    public class SunVoteManager : IDisposable
    {
#if Android
#elif __IOS__
#else
        [DllImport("kernel32.dll")]
        private static extern IntPtr SetDllDirectory(string dllToLoad);
#endif

        const int LICENSE_MODE = 1;
        const string LICENSE_PASSWORD = "SUNARS2013";
        private SunVoteManager()
        {
#if Android
#elif __IOS__
#else
            var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            path = Path.Combine(path, Environment.Is64BitProcess ? "x64" : "x86");
            SetDllDirectory(path);
#endif
            //获得授权
            SunVoteWrapper.License(LICENSE_MODE, LICENSE_PASSWORD);
            SetLogOn(LogOnMode.DISABLED);
            //设置事件回调函数
            SunVoteWrapper.SetConnectEventCallBack(ConnectEventCallBackFunction);
            SunVoteWrapper.SetHDParamEventCallBack(HDParamEventCallbackFunction);
            SunVoteWrapper.SetKeyEventCallBack(KeyEventCallBackFunction);
            SunVoteWrapper.SetVoteEventCallBack(VoteEventCallBackFunction);
        }
        private int _ConnectedBaseID = -1;
        private static SunVoteManager _Manager;

        public static SunVoteManager Manager
        {
            get
            {
                if (_Manager == null)
                {
                    _Manager = new SunVoteManager();
                }
                return _Manager;
            }
        }

        public int ConnectedBaseID
        {
            get
            {
                return _ConnectedBaseID;
            }
        }

        public static event Action<SunVoteEventArgs> OnConnect;
        public static event Action<SunVoteEventArgs> OnKey;
        public static event Action<SunVoteEventArgs> OnVote;
        public static event Action<SunVoteEventArgs> OnSetParam;
        public static event Action<string> OnLog;

        #region callback functions
#if __IOS__
        [ObjCRuntime.MonoPInvokeCallback(typeof(SunVoteWrapper.HDParamEventCallbackDelegate))]
#endif
        private static void HDParamEventCallbackFunction(int iBaseID, int iMode, string sInfo)
        {
            DoLog($"设置参数回调, iBaseID:{iBaseID}, iMode:{iMode}, sInfo:{sInfo}");
            if (OnSetParam != null)
            {
                OnSetParam(new SunVoteEventArgs(iBaseID, iMode, sInfo));
            }
        }

#if __IOS__
        [ObjCRuntime.MonoPInvokeCallback(typeof(SunVoteWrapper.KeyEventCallbackDelegate))]
#endif
        private static void KeyEventCallBackFunction(string KeyID, int iMode, float Time, string sInfo)
        //private void KeyEventCallBackFunction(int iBaseID, int KeyID, string keySN, int iMode, float Time, string sInfo)
        {
            DoLog($"键盘事件回调, keyID:{KeyID}, iMode:{iMode}, Time:{Time}, sInfo:{sInfo}");
            if (OnKey != null)
            {
                OnKey(new SunVoteEventArgs(_Manager._ConnectedBaseID, KeyID, string.Empty, iMode, Time, sInfo));
            }
        }

#if __IOS__
        [ObjCRuntime.MonoPInvokeCallback(typeof(SunVoteWrapper.ConnectEventCallbackDelegate))]
#endif
        private static void ConnectEventCallBackFunction(int iBaseID, int iMode, string sInfo)
        {
            DoLog($"连接事件回调, iBaseID:{iBaseID}, iMode:{iMode}, sInfo:{sInfo}");
            _Manager._ConnectedBaseID = iBaseID;
            if (OnConnect != null)
            {
                OnConnect(new SunVoteEventArgs(iBaseID, iMode, sInfo));
            }
        }

#if __IOS__
        [ObjCRuntime.MonoPInvokeCallback(typeof(SunVoteWrapper.VoteEventCallbackDelegate))]
#endif
        private static void VoteEventCallBackFunction(int iBaseID, int iMode, string sInfo)
        {
            DoLog($"投票回调, iBaseID:{iBaseID}, iMode:{iMode}, sInfo:{sInfo}");
            if (OnVote != null)
            {
                OnVote(new SunVoteEventArgs(iBaseID, iMode, sInfo));
            }
        }
        #endregion

        private static void DoLog(string logMessage)
        {
            if(OnLog!=null)
            {
                OnLog(logMessage);
            }
        }

        public bool SetLogOn(LogOnMode mode = LogOnMode.DISABLED)
        {
            return SunVoteWrapper.SetLogOn((int)mode) == 1;
        }
        /// <summary>
        /// 以USB方式连接基站
        /// </summary>
        /// <param name="iBaseID"></param>
        public int Connect_USB(int iBaseID)
        {
            if (iBaseID < 1 || iBaseID > 32)
            {
                return -9;
            }
            DoLog($"开始以USB方式连接基站");
            return SunVoteWrapper.Connect((int)ConnectType.CONN_TYPE_USB, iBaseID.ToString());
        }

        /// <summary>
        /// 以TCPIP方式连接基站
        /// </summary>
        /// <param name="iBaseID"></param>
        public int Connect_TCPIP(string ipAddress)
        {
            DoLog($"开始以TCP/IP方式连接基站");
            return SunVoteWrapper.Connect((int)ConnectType.CONN_TYPE_TCPIP, ipAddress);
        }

        public int DisConnect()
        {
            DoLog($"断开基站连接");
            return SunVoteWrapper.Disconnect(_ConnectedBaseID);
        }

        /// <summary>
        /// 开始选择投票
        /// </summary>
        /// <param name="displayType"></param>
        /// <param name="alterMode"></param>
        /// <param name="securityMode"></param>
        /// <param name="forceMode"></param>
        /// <param name="optionsCount"></param>
        /// <param name="maxChoice"></param>
        /// <returns></returns>
        public int StartChoice(ChoiceDisplayType displayType = ChoiceDisplayType.Letter, AlterMode alterMode = AlterMode.Enable, SecurityMode securityMode = SecurityMode.No, ForceChoiceMode forceMode = ForceChoiceMode.No, int optionsCount = 4, int maxChoice = 1)
        {
            if (optionsCount <= 0)
            {
                return -9;
            }
            if (maxChoice <= 0)
            {
                return -99;
            }
            if (maxChoice > optionsCount)
            {
                return -999;
            }
            DoLog($"开始选择投票");
            return SunVoteWrapper.VoteStart((int)VoteType.VoteType_Choice, $"{(int)displayType},{(int)alterMode},{(int)securityMode},{(int)forceMode},{optionsCount},{maxChoice}");
        }

        ///// <summary>
        ///// 开始选择投票
        ///// </summary>
        ///// <param name="displayType"></param>
        ///// <param name="alterMode"></param>
        ///// <param name="securityMode"></param>
        ///// <param name="forceMode"></param>
        ///// <param name="optionsCount"></param>
        ///// <param name="maxChoice"></param>
        ///// <returns></returns>
        //public int StartChoice(int iBaseID, ChoiceDisplayType displayType = ChoiceDisplayType.Letter, AlterMode alterMode = AlterMode.Enable, SecurityMode securityMode = SecurityMode.No, ForceChoiceMode forceMode = ForceChoiceMode.No, int optionsCount = 4, int maxChoice = 1)
        //{
        //    if (optionsCount <= 0)
        //    {
        //        return -9;
        //    }
        //    if (maxChoice <= 0)
        //    {
        //        return -99;
        //    }
        //    if (maxChoice > optionsCount)
        //    {
        //        return -999;
        //    }
        //    DoLog($"开始选择投票2");
        //    return SunVoteWrapper.VoteStart2(iBaseID, (int)VoteType.VoteType_Choice, $"{(int)displayType},{(int)alterMode},{(int)securityMode},{(int)forceMode},{optionsCount},{maxChoice}");
        //}
        /// <summary>
        /// 开始数值投票
        /// </summary>
        /// <param name="securityMode"></param>
        /// <param name="forceMode"></param>
        /// <returns></returns>
        public int StartNumber(SecurityMode securityMode = SecurityMode.No, ForceChoiceMode forceMode = ForceChoiceMode.No)
        {
            DoLog($"开始数值投票");
            return SunVoteWrapper.VoteStart((int)VoteType.VoteType_Number, $"1,{(int)securityMode},{(int)forceMode}");
        }
        ///// <summary>
        ///// 开始数值投票
        ///// </summary>
        ///// <param name="securityMode"></param>
        ///// <param name="forceMode"></param>
        ///// <returns></returns>
        //public int StartNumber(int iBaseID, SecurityMode securityMode = SecurityMode.No, ForceChoiceMode forceMode = ForceChoiceMode.No)
        //{
        //    DoLog($"开始选择投票2");
        //    return SunVoteWrapper.VoteStart2(iBaseID, (int)VoteType.VoteType_Number, $"1,{(int)securityMode},{(int)forceMode}");
        //}
        /// <summary>
        /// 停止投票
        /// </summary>
        /// <returns></returns>
        public int StopVote()
        {
            DoLog($"开始停止投票");
            return SunVoteWrapper.VoteStop();
        }
        ///// <summary>
        ///// 停止投票
        ///// </summary>
        ///// <returns></returns>
        //public int StopVote(int iBaseID)
        //{
        //    DoLog($"开始停止投票2");
        //    return SunVoteWrapper.VoteStop2(iBaseID);
        //}
        /// <summary>
        /// 开始抢答
        /// </summary>
        /// <returns></returns>
        public int StartRush()
        {
            DoLog($"开始抢答投票");
            return SunVoteWrapper.VoteStart((int)VoteType.VoteType_Quiz, $"0");
        }

        public void Dispose()
        {
            SunVoteWrapper.Disconnect(_ConnectedBaseID);
            _ConnectedBaseID = -1;
        }
        /// <summary>
        /// 连接方式
        /// </summary>
        public enum ConnectType
        {
            CONN_TYPE_USB = 1,
            CONN_TYPE_TCPIP
        }
        /// <summary>
        /// 日志模式
        /// </summary>
        public enum LogOnMode
        {
            /// <summary>
            /// 禁用
            /// </summary>
            DISABLED = 0,
            /// <summary>
            /// 仅日志
            /// </summary>
            LOG_ONLY,
            /// <summary>
            /// 日志和调试信息
            /// </summary>
            LOG_DEBGU
        }

        internal enum VoteType
        {
            /// <summary>
            /// 空闲模式(停止)
            /// </summary>
            VoteType_Free = 0,
            /// <summary>
            /// 签到
            /// </summary>
            VoteType_Signin = 1,
            /// <summary>
            /// //表决
            /// </summary>
            VoteType_Vote = 2,
            /// <summary>
            /// 数值（单项评分模式）
            /// </summary>
            VoteType_Number = 4,
            /// <summary>
            /// 判断
            /// </summary>
            VoteType_TrueFalse = 5,
            /// <summary>
            /// 模拟测试
            /// </summary>
            VoteType_KeyPadTest = 9,
            /// <summary>
            /// 选择
            /// </summary>
            VoteType_Choice = 10,
            /// <summary>
            /// 排序
            /// </summary>
            VoteType_Sequence = 11,
            /// <summary>
            /// 填空
            /// </summary>
            VoteType_FillBlanks = 12,
            /// <summary>
            /// 抢答
            /// </summary>
            VoteType_Quiz = 13,
            /// <summary>
            ///测验
            /// </summary>
            VoteType_Examination = 14
        };
        /// <summary>
        /// 选项显示方式
        /// </summary>
        public enum ChoiceDisplayType
        {
            /// <summary>
            /// 字母
            /// </summary>
            Letter = 1,
            /// <summary>
            /// 数字
            /// </summary>
            Number
        }

        /// <summary>
        /// 修改模式
        /// </summary>
        public enum AlterMode
        {
            /// <summary>
            /// 提交后可以修改
            /// </summary>
            Enable = 1,
            /// <summary>
            /// 提交后不能修改
            /// </summary>
            Disable = 0
        }

        /// <summary>
        /// 保密模式
        /// </summary>
        public enum SecurityMode
        {
            /// <summary>
            /// 显示保密
            /// </summary>
            Yes = 1,
            /// <summary>
            /// 不保密
            /// </summary>
            No = 0
        }

        /// <summary>
        /// 迫选模式
        /// </summary>
        public enum ForceChoiceMode
        {
            /// <summary>
            /// 迫选
            /// </summary>
            Yes = 1,
            /// <summary>
            /// 可以缺选
            /// </summary>
            No = 0
        }
    }
}
